﻿//#pragma once
//#include "XyNet/Common/FileSystem.h"
//#include "XyNet/Common/ProcessTimer.h"
//#include "XyNet/Channel/RpcSocketChannel.h"
//#include "XyNet/Protocol/cpp/Rpc.service.h"
//#include <boost/bimap.hpp>
//
//namespace XyNet
//{
//	class XYNET_API Downloader
//	{
//	public:
//		class XYNET_API Task : public enable_shared_from_this<Task>
//		{
//		public:
//			enum State
//			{
//				Prepare,    // 获取文件、目录、子目录信息
//				Pause,  // 暂停
//				Download,   // 下载中
//				Finish  // 完成
//			};
//
//		private:
//			struct DownloadFileInfo
//			{
//				DownloadFileInfo(const string& link,
//					const FileSystem::Path& path, int64 size, const Bytes& hash)
//					: _link(link), _path(path), _size(size), _hash(hash)
//					, _nextDownloadPosition(0) {}
//
//				/// 下载连接
//				string _link;
//				/// 要下载到的路径（含文件名）
//				FileSystem::Path _path;
//				/// 尺寸
//				int64 _size;
//				/// 哈希
//				Bytes _hash;
//				/// 下一个下载位置
//				int64 _nextDownloadPosition;
//				/// 下载中的块位置列表
//				set<int64> _downloadingBlockPositions;
//			};
//
//		public:
//			Task(weak_ptr<RpcChannel> channel, const string& link,
//				const FileSystem::Path& downloadPath, bool downloadNow);
//			Task(weak_ptr<RpcChannel> channel, const string& link,
//				const Bytes& localLink, bool downloadNow);
//
//			/// 获取连接
//			const string& getLink() const;
//			/// 获取名称
//			const string& getName() const;
//			/// 获取路径
//			const FileSystem::Path& getPath() const;
//
//			/// 获取总尺寸
//			int64 getTotalSize() const;
//			/// 获取经过hash验证后需要下载的尺寸
//			int64 getNeedDownloadSize() const;
//			/// 获取下载完成的尺寸
//			int64 getDownloadedSize() const;
//
//			/// 获取准备时间（秒）
//			double getPrepareTime();
//			/// 获取下载时间（秒）
//			double getDownloadTime();
//
//			/// 开始任务
//			void start();
//			/// 暂停任务
//			void pause();
//
//			/// 获取状态
//			State getState() const;
//
//		private:
//			/// 准备下一个
//			void prepareNext();
//			/// 下载下一个
//			void downloadNext();
//
//			/// 创建要下载的目录（会删除该路径的文件）
//			void createDownloadDirectories(const FileSystem::Path& path);
//			/// 添加需要下载的文件（会删除该路径的目录）
//			void addNeedDownloadFile(shared_ptr<DownloadFileInfo> fileInfo);
//			/// 初始化下载文件信息
//			void initDownloadFileInfo(shared_ptr<DownloadFileInfo> fileInfo);
//			/// 获取下载中的文件数据
//			void getDownloadingFileData(shared_ptr<DownloadFileInfo> fileInfo);
//
//		private:
//			/// 通道
//			weak_ptr<RpcChannel> _weakChannel;
//			/// 下载链接
//			string _link;
//			/// 任务名
//			string _name;
//			/// 下载到的路径（下载路径/文件（夹）名）
//			FileSystem::Path _path;
//
//			/// 总尺寸
//			int64 _totalSize;
//			/// 经过hash验证后需要下载的尺寸
//			int64 _needDownloadSize;
//			/// 下载完成的尺寸
//			int64 _downloadedSize;
//
//			/// 任务状态
//			State _state;
//			/// 是否立即下载
//			bool _downloadNow;
//
//			/// 计时器
//			ProcessTimer _timer;
//			/// 准备时间
//			double _prepareTime;
//			/// 下载时间（不包含准备时间）
//			double _downloadTime;
//
//			/// 需要准备的连接下载路径对列表
//			vector<pair<Bytes, FileSystem::Path>> _needPrepareLinkDownloadPathPairs;
//			/// 准备中的连接下载路径对列表
//			map<Bytes, FileSystem::Path> _preparingLinkDownloadPathPairs;
//
//			/// 需要下载的下载文件信息列表
//			deque<shared_ptr<DownloadFileInfo>> _needDownloadFileInfos;
//			/// 下载中的下载文件信息列表
//			list<shared_ptr<DownloadFileInfo>> _downloadingFileInfos;
//
//			/// 线程数量
//			static const int ThreadCount;
//			/// 下载块大小
//			static const int _blockSize;
//		};
//
//	public:
//		Downloader();
//
//		/// 创建任务（downloadDirectory是不含文件名的下载目录）
//		void createTask(weak_ptr<RpcChannel> weakChannel, const string& link, 
//			const FileSystem::Path& downloadDirectory, bool downloadNow = true);
//		/// 移除任务
//		void removeTask(const string& link);
//		/// 移除已完成的任务
//		void removeFinishedTasks();
//		/// 获取任务
//		shared_ptr<Task> getTask(const string& link);
//		/// 获取任务迭代器
//		ConstIterator<shared_ptr<Task>> getTasksIterator() const;
//
//		/// 获取路径连接
//		static string getPathLink(const FileSystem::Path& path);
//		/// 获取连接路径
//		static FileSystem::Path getLinkPath(const string& link);
//
//		/// 获取哈希尺寸
//		static int getHashSize();
//		/// 获取文件哈希
//		static Bytes getFileHash(const FileSystem::Path& path);
//		/// 创建哈希文件（可以用已经算好的hash）
//		static Bytes createHashFile(const FileSystem::Path& path, const Bytes& inputHash = "");
//
//		/// 获取目录哈希
//		static const Bytes& getDirectoryHash(const FileSystem::Path& path);
//
//		/// 获取文件对应的哈希文件路径
//		static FileSystem::Path getFileHashPath(const FileSystem::Path& path);
//
//	private:
//		/// 任务列表
//		vector<shared_ptr<Task>> _tasks;
//
//		/// 目录路径连接双向映射
//		static boost::bimap<FileSystem::Path, string> _dirPathLinkBimap;
//		/// 目录哈希长度
//		static const size_t _hashSize;
//	};
//}